﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using AOUtils.Libraries;
using System.Threading;
using System.Windows.Threading;
using System.Collections;
using System.Diagnostics;

namespace AOUtils
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Runner : Window
    {
        private Dictionary<EquipmentPage, EquipmentGrid> grids = new Dictionary<EquipmentPage, EquipmentGrid>();
        private delegate void ProgressReported(int percent);
        private delegate void UpdateProgressBarHandler(long i);
        private delegate void UpdateTextBoxHandler(string message, bool append);
        private delegate void EnableControlsHandler(bool state);
        private delegate void ItemSourceHandler(ItemsControl control, IEnumerable itemsSource);
        private delegate void PlaceItemOnGridHandler(OptimizedItem item, Grid grid);
        private delegate void OptimizeSelectionHandler(Grid grid);
        private delegate void CreateStatsHandler();
        private delegate void OptimizeWeaponSelectionHandler();
        private ItemsHandler itemshandler = new ItemsHandler();
        private ItemSearcher searcher = new ItemSearcher();

        public Runner()
        {
            InitializeComponent();
            grids.Add(EquipmentPage.Armor, clothingGrid);
            grids.Add(EquipmentPage.Weapon, weaponGrid);
            grids.Add(EquipmentPage.Implant, implantGrid);
            grids.Add(EquipmentPage.Spirit, implantGrid);
            itemshandler.ProgressUpdate += new EventHandler<ProgressUpdateEventArgs>(ProgressUpdate);
            itemshandler.ResourcesLoaded += new EventHandler<EventArgs>(ResourcesLoaded);
            searcher.ProgressUpdate += new EventHandler<ProgressUpdateEventArgs>(ProgressUpdate);
            searcher.ItemFound += new EventHandler<ItemFoundEventArgs>(ItemFound);
            searcher.SearchFinished += new EventHandler<EventArgs>(SearchFinished);
        }

        private void SearchFinished(object sender, EventArgs e)
        {
            EnableControls(true);
            OptimizeSelection(grids[EquipmentPage.Armor]);
            OptimizeSelection(grids[EquipmentPage.Weapon]);
            OptimizeSelection(grids[EquipmentPage.Implant]);
            OptimizeWeaponSelection();
            CreateStats();
        }

        private void OptimizeWeaponSelection()
        {
            if (Dispatcher.CheckAccess())
            {
                IconDockPanel rightHandPanel = (IconDockPanel)weaponGrid.Children[2];
                IconDockPanel leftHandPanel = (IconDockPanel)weaponGrid.Children[12];
                if (rightHandPanel.SelectedItem == null || leftHandPanel.SelectedItem == null)
                    return;
                if (((rightHandPanel.SelectedItem.IsDualWieldable && rightHandPanel.SelectedItem.MultiMelee > 0) &&
                    (leftHandPanel.SelectedItem.IsDualWieldable && leftHandPanel.SelectedItem.MultiMelee > 0)) ||
                    ((rightHandPanel.SelectedItem.IsDualWieldable && rightHandPanel.SelectedItem.MultiRanged > 0) &&
                    (leftHandPanel.SelectedItem.IsDualWieldable && leftHandPanel.SelectedItem.MultiRanged > 0)))
                    return;
                //find best dualwieldable ranged
                OptimizedItem rangedright = null;
                OptimizedItem rangedleft = null;
                OptimizedItem meleeright = null;
                OptimizedItem meleeleft = null;
                OptimizedItem nondualright = null;
                OptimizedItem nondualleft = null;
                bool rrset = false;
                bool rlset = false;
                bool mrset = false;
                bool mlset = false;
                bool ndset = false;
                OptimizedItem temp = null;
                for (int i = 0; i < rightHandPanel.ContextMenu.Items.Count - 1; i++)
                {
                    temp = ((rightHandPanel.ContextMenu.Items[i]) as MenuItem).Tag as OptimizedItem;
                    if (!rrset && temp.IsDualWieldable && temp.WeaponType == AttackValueTypes.Ranged)
                    {
                        rangedright = temp;
                        rrset = true;
                    }
                    if (!mrset && temp.IsDualWieldable && temp.WeaponType == AttackValueTypes.Melee)
                    {
                        meleeright = temp;
                        mrset = true;
                    }
                    if (!ndset && !temp.IsDualWieldable)
                    {
                        nondualright = temp;
                        ndset = true;
                    }
                }
                ndset = false;
                for (int i = 0; i < leftHandPanel.ContextMenu.Items.Count - 1; i++)
                {
                    temp = ((leftHandPanel.ContextMenu.Items[i]) as MenuItem).Tag as OptimizedItem;
                    if (!rlset && temp.IsDualWieldable && temp.WeaponType == AttackValueTypes.Ranged)
                    {
                        rangedleft = temp;
                        rlset = true;
                    }
                    if (!mlset && temp.IsDualWieldable && temp.WeaponType == AttackValueTypes.Melee)
                    {
                        meleeleft = temp;
                        mlset = true;
                    }
                    if (!ndset && !temp.IsDualWieldable)
                    {
                        nondualleft = temp;
                        ndset = true;
                    }
                }

                int rangedpoints = 0;
                int meleepoints = 0;
                int nondualpoints = 0;
                bool useright = true;

                if (rangedright != null)
                    rangedpoints += rangedright.GetAbsoluteSkillValues()[rangedright.SortSkill];
                if (rangedleft != null)
                    rangedpoints += rangedleft.GetAbsoluteSkillValues()[rangedleft.SortSkill];

                if (meleeright != null)
                    meleepoints += meleeright.GetAbsoluteSkillValues()[meleeright.SortSkill];
                if (meleeleft != null)
                    meleepoints += meleeleft.GetAbsoluteSkillValues()[meleeleft.SortSkill];

                if(nondualright != null && nondualleft == null)
                    nondualpoints = nondualright.GetAbsoluteSkillValues()[nondualright.SortSkill];
                else if (nondualright == null && nondualleft != null)
                    nondualpoints = nondualleft.GetAbsoluteSkillValues()[nondualleft.SortSkill];
                else if (nondualright != null && nondualleft != null)
                {
                    int tmpr = nondualright.GetAbsoluteSkillValues()[nondualright.SortSkill];
                    int tmpl = nondualleft.GetAbsoluteSkillValues()[nondualleft.SortSkill];
                    if (tmpr >= tmpl)
                        nondualpoints = tmpr;
                    else
                    {
                        nondualpoints = tmpl;
                        useright = false;
                    }
                }

                if (rangedpoints > meleepoints && rangedpoints > nondualpoints)
                {
                    rightHandPanel.SelectedItem = rangedright;
                    leftHandPanel.SelectedItem = rangedleft;
                }
                else if (meleepoints > rangedpoints && meleepoints > nondualpoints)
                {
                    rightHandPanel.SelectedItem = meleeright;
                    leftHandPanel.SelectedItem = meleeleft;
                }
                else
                {
                    if (useright)
                    {
                        rightHandPanel.SelectedItem = nondualright;
                        leftHandPanel.SelectedItem = null;
                    }
                    else
                    {
                        rightHandPanel.SelectedItem = null;
                        leftHandPanel.SelectedItem = nondualleft;
                    }
                }
            }
            else
            {
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new OptimizeWeaponSelectionHandler(OptimizeWeaponSelection));
            }
        }
        
        private void CreateStats()
        {
            SortedDictionary<string, int> skills = new SortedDictionary<string, int>();
            List<string> skillindex = new List<string>();

            if (Dispatcher.CheckAccess())
            {
                foreach (IconDockPanel panel in grids[EquipmentPage.Armor].Children)
                {
                    OptimizedItem item = panel.SelectedItem;
                    if (item == null)
                        continue;
                    foreach (KeyValuePair<string, int> kvp in item.GetSkillValues())
                    {
                        if (!skills.ContainsKey(kvp.Key))
                        {
                            skillindex.Add(kvp.Key);
                            skills.Add(kvp.Key, kvp.Value);
                        }
                        else
                            skills[kvp.Key] += kvp.Value;
                    }
                }
                foreach (IconDockPanel panel in grids[EquipmentPage.Implant].Children)
                {
                    OptimizedItem item = panel.SelectedItem;
                    if (item == null)
                        continue;
                    foreach (KeyValuePair<string, int> kvp in item.GetSkillValues())
                    {
                        if (!skills.ContainsKey(kvp.Key))
                        {
                            skillindex.Add(kvp.Key);
                            skills.Add(kvp.Key, kvp.Value);
                        }
                        else
                            skills[kvp.Key] += kvp.Value;
                    }
                }
                foreach (IconDockPanel panel in grids[EquipmentPage.Weapon].Children)
                {
                    OptimizedItem item = panel.SelectedItem;
                    if (item == null)
                        continue;
                    foreach (KeyValuePair<string, int> kvp in item.GetSkillValues())
                    {
                        if (!skills.ContainsKey(kvp.Key))
                        {
                            skillindex.Add(kvp.Key);
                            skills.Add(kvp.Key, kvp.Value);
                        }
                        else
                            skills[kvp.Key] += kvp.Value;
                    }
                }
                skillindex.Sort();
                StringBuilder tmp = new StringBuilder();
                for (int i = 0; i < skills.Count/3; i++)
                {
                    if (skills.Count % 3 == 0)
                        tmp.AppendFormat("{0,-25}:{1,7} | {2,-25}:{3,7} | {4,-25}:{5,7}" + Environment.NewLine, skillindex[i], skills[skillindex[i]], skillindex[i + (skills.Count / 3)], skills[skillindex[i + (skills.Count / 3)]], skillindex[i + skills.Count / 3 * 2], skills[skillindex[i + skills.Count / 3 * 2]]);
                    else if (skills.Count % 3 == 1)
                        tmp.AppendFormat("{0,-25}:{1,7} | {2,-25}:{3,7} | {4,-25}:{5,7}" + Environment.NewLine, skillindex[i], skills[skillindex[i]], skillindex[i + (skills.Count / 3) + 1], skills[skillindex[i + (skills.Count / 3) + 1]], skillindex[i + skills.Count / 3 * 2 + 1], skills[skillindex[i + skills.Count / 3 * 2 + 1]]);
                    else
                        tmp.AppendFormat("{0,-25}:{1,7} | {2,-25}:{3,7} | {4,-25}:{5,7}" + Environment.NewLine, skillindex[i], skills[skillindex[i]], skillindex[i + (skills.Count / 3) + 1], skills[skillindex[i + (skills.Count / 3) + 1]], skillindex[i + skills.Count / 3 * 2 + 2], skills[skillindex[i + skills.Count / 3 * 2 + 2]]);
                }
                if (skills.Count % 3 == 1)
                    tmp.AppendFormat("{0,-25}:{1,7}", skillindex[skills.Count / 3], skills[skillindex[skills.Count / 3]]);
                if (skills.Count % 3 == 2)
                    tmp.AppendFormat("{0,-25}:{1,7} | {2,-25}:{3,7}", skillindex[skills.Count / 3], skills[skillindex[skills.Count / 3]], skillindex[skills.Count / 3 * 2 + 1], skills[skillindex[skills.Count / 3 * 2 + 1]]);
                outputTextBox.Text = tmp.ToString();
            }
            else
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new CreateStatsHandler(CreateStats));
        }

        private void ItemFound(object sender, ItemFoundEventArgs e)
        {
            PlaceItemOnGrid(e.Item, grids[e.Item.EquipmentPage]);
        }

        private void ResourcesLoaded(object sender, EventArgs e)
        {
            SetItemSource(skillsListBox, itemshandler.Skills);
            EnableControls(true);
        }

        private void SetItemSource(ItemsControl control, IEnumerable itemsSource)
        {
            if (Dispatcher.CheckAccess())
                control.ItemsSource = itemsSource;
            else
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new ItemSourceHandler(SetItemSource), control, itemsSource);
        }

        private void ProgressUpdate(object sender, ProgressUpdateEventArgs e)
        {
            UpdateTextBox(e.Message, true);
            UpdateProgressBar(e.Number);
        }

        private void UpdateTextBox(string message, bool append)
        {
            if (Dispatcher.CheckAccess())
            {
                if (message != string.Empty)
                {
                    if (append)
                        outputTextBox.Text += message + Environment.NewLine;
                    else
                        outputTextBox.Text = message + Environment.NewLine;
                }
            }
            else
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new UpdateTextBoxHandler(UpdateTextBox), message, append);
        }

        private void UpdateProgressBar(long i)
        {
            if (Dispatcher.CheckAccess())
                progressBar.Value = i;
            else
                Dispatcher.BeginInvoke(DispatcherPriority.Normal, new UpdateProgressBarHandler(UpdateProgressBar), i);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            EnableControls(false);
            Thread t = new Thread(new ThreadStart(itemshandler.LoadResources));
            t.Start();
        }

        private void EnableControls(bool state)
        {
            if (Dispatcher.CheckAccess())
            {
                searchButton.IsEnabled = state;
                clearButton.IsEnabled = state;
                professionComboBox.IsEnabled = state;
                breedComboBox.IsEnabled = state;
                skillsListBox.IsEnabled = state;
                factionComboBox.IsEnabled = state;
                useSocialArmorCheckBox.IsEnabled = state;
                levelNumericUpDown.IsEnabled = state;
            }
            else
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new EnableControlsHandler(EnableControls), state);
        }

        private void searchButton_Click(object sender, RoutedEventArgs e)
        {
            ClearForm();
            if (skillsListBox.SelectedValue == null)
            {
                MessageBox.Show("No skill selected", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            EnableControls(false);

            SearchCriteria criteria = new SearchCriteria();
            criteria.Breed = (Breed)breedComboBox.SelectedValue;
            criteria.Profession = (Professions)professionComboBox.SelectedValue;
            criteria.Faction = (Faction)factionComboBox.SelectedValue;
            criteria.Skill = skillsListBox.SelectedValue.ToString();
            criteria.Level = levelNumericUpDown.Value;
            criteria.UseSocial = (bool)useSocialArmorCheckBox.IsChecked;
            criteria.Xml = itemshandler.Xml;
            Thread t = new Thread(new ParameterizedThreadStart(searcher.Search));
            t.Start(criteria);
        }

        private void SelectPlacement(OptimizedItem item, Grid grid, int currentGridIndex, int compareGridIndex, int maxIndex, int currentContextMenuIndex)
        {
            if (item.GetAbsoluteSkillValues()[item.SortSkill] <= 0 || currentGridIndex >= grid.Children.Count || compareGridIndex >= grid.Children.Count)
                return;
            IconDockPanel currentPanel = grid.Children[currentGridIndex] as IconDockPanel;
            IconDockPanel comparePanel = grid.Children[compareGridIndex] as IconDockPanel;

            if ((!item.Unique || compareGridIndex == maxIndex) && (item.Slot & currentPanel.Slot) != Slot.None)
                currentPanel.SelectedItem = item;
            else if ((item.Slot & comparePanel.Slot) == Slot.None)
                SelectPlacement(item, grid, currentGridIndex, ++compareGridIndex, maxIndex, currentContextMenuIndex);
            else if (comparePanel.SelectedItem != null && !comparePanel.SelectedItem.Name.Equals(item.Name))
                SelectPlacement(item, grid, currentGridIndex, ++compareGridIndex, maxIndex, currentContextMenuIndex);
            else if (comparePanel.SelectedItem != null && comparePanel.SelectedItem.Name.Equals(item.Name))
            {
                if (currentPanel.HasNextItem && !comparePanel.HasNextItem)
                    SelectPlacement(currentPanel.NextItem, grid, currentGridIndex, 0, maxIndex, ++currentPanel.SelectedIndex);
                else if (!currentPanel.HasNextItem && comparePanel.HasNextItem)
                {
                    SelectPlacement(item, grid, currentGridIndex, ++compareGridIndex, maxIndex, currentPanel.SelectedIndex);
                    if (comparePanel.HasNextItem)
                        SelectPlacement(comparePanel.NextItem, grid, compareGridIndex - 1, 0, maxIndex, ++comparePanel.SelectedIndex);
                }
                else if (currentPanel.HasNextItem && comparePanel.HasNextItem)
                {
                    if (currentPanel.NextItem > comparePanel.NextItem)
                        SelectPlacement(currentPanel.NextItem, grid, currentGridIndex, 0, maxIndex, ++currentPanel.SelectedIndex);
                    else if (currentPanel.NextItem < comparePanel.NextItem)
                    {
                        SelectPlacement(item, grid, currentGridIndex, ++compareGridIndex, maxIndex, currentPanel.SelectedIndex);
                        if (comparePanel.HasNextItem)
                            SelectPlacement(comparePanel.NextItem, grid, compareGridIndex - 1, 0, maxIndex, ++comparePanel.SelectedIndex);
                    }
                    else if (currentPanel.NextItem == currentPanel.NextItem)
                    {
                        SelectPlacement(currentPanel.NextItem, grid, currentGridIndex, 0, maxIndex, ++currentPanel.SelectedIndex);
                    }
                }
            }                
        }

        public void OptimizeSelection(Grid grid)
        {
            if (Dispatcher.CheckAccess())
            {
                for (int x = 0; x < grid.Children.Count; x++)
                {
                    IconDockPanel panel = (IconDockPanel)grid.Children[x];
                    if (panel.ContextMenu != null)
                    {
                        OptimizedItem item = (OptimizedItem)((MenuItem)panel.ContextMenu.Items[0]).Tag;
                        SelectPlacement(item, grid, x, 0, x, 0);
                    }
                }
            }
            else
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new OptimizeSelectionHandler(OptimizeSelection), grid);
        }

        private MenuItem CreateMenuItem(OptimizedItem item)
        {
            MenuItem mi = new MenuItem();
            mi.Tag = item;
            mi.Header = item.Name + " (" + item.GetSkillValues()[item.SortSkill] + ")";
            mi.ToolTip = item.Name + Environment.NewLine + "Ql " + item.Ql + Environment.NewLine;
            if (item.Unique)
                mi.ToolTip += "Unique" + Environment.NewLine;
            if (item.NoDrop)
                mi.ToolTip += "NoDrop" + Environment.NewLine;
            if (item.Social)
                mi.ToolTip += "Social" + Environment.NewLine;
            mi.ToolTip += Environment.NewLine;

            if (item.OnWear.Functions[FunctionType.Modify].Targets.Contains(TargetType.Wearer))
            {
                for (int i = 0; i < item.OnWear.Functions[FunctionType.Modify].Targets[TargetType.Wearer].Arguments.Count; i += 2)
                {
                    OptimizedArgument arg1 = item.OnWear.Functions[FunctionType.Modify].Targets[TargetType.Wearer].Arguments[i];
                    OptimizedArgument arg2 = item.OnWear.Functions[FunctionType.Modify].Targets[TargetType.Wearer].Arguments[i + 1];
                    if (arg1.Requirements.Count > 0)
                    {
                        foreach (OptimizedRequirement req in arg1.Requirements)
                        {
                            mi.ToolTip += req.Statistic + " " + req.Operator.ToString() + " " + req.Value + " " + req.ChildOp + Environment.NewLine;
                        }
                    }
                    mi.ToolTip += "\t" + arg1.Value + " " + arg2.Value + Environment.NewLine;
                }
            }
            if (item.OnWear.Functions[FunctionType.Modify].Targets.Contains(TargetType.Target))
            {
                for (int i = 0; i < item.OnWear.Functions[FunctionType.Modify].Targets[TargetType.Target].Arguments.Count; i += 2)
                {
                    OptimizedArgument arg1 = item.OnWear.Functions[FunctionType.Modify].Targets[TargetType.Target].Arguments[i];
                    OptimizedArgument arg2 = item.OnWear.Functions[FunctionType.Modify].Targets[TargetType.Target].Arguments[i + 1];
                    if (arg1.Requirements.Count > 0)
                    {
                        foreach (OptimizedRequirement req in arg1.Requirements)
                        {
                            mi.ToolTip += req.Statistic + " " + req.Operator.ToString() + " " + req.Value + " " + req.ChildOp + Environment.NewLine;
                        }
                    }
                    mi.ToolTip += "\t" + arg1.Value + " " + arg2.Value + Environment.NewLine;
                }
            }
            return mi;
        }

        private void PlaceItemOnGrid(OptimizedItem item, Grid grid)
        {

            if (Dispatcher.CheckAccess())
            {
                foreach (IconDockPanel panel in grid.Children)
                {
                    if ((panel.Slot & item.Slot) > 0)
                    {
                        panel.AddItem(CreateMenuItem(item));
                    }
                }
            }
            else
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new PlaceItemOnGridHandler(PlaceItemOnGrid), item, grid);   
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            ClearForm();
        }

        private void ClearForm()
        {
            outputTextBox.Text = string.Empty;
            weaponGrid.Clear();
            clothingGrid.Clear();
            implantGrid.Clear();
        }

        private void SelectedItemChangedHandler(object sender, ItemChangedEventArgs e)
        {
            CreateStats();
        }

        private void ExportAunoClick(object sender, RoutedEventArgs e)
        {
            string url = BuildAunoUrl();
            Process.Start(new ProcessStartInfo(url));
        }

        private string BuildAunoUrl()
        {
            Dictionary<Slot, int> weaponsmap = new Dictionary<Slot, int>();
            weaponsmap.Add(Slot.HUD1, 2);
            weaponsmap.Add(Slot.HUD2, 32768);
            weaponsmap.Add(Slot.HUD3, 4);
            weaponsmap.Add(Slot.UTIL1, 8);
            weaponsmap.Add(Slot.UTIL2, 16);
            weaponsmap.Add(Slot.UTIL3, 32);
            weaponsmap.Add(Slot.RightHand, 64);
            weaponsmap.Add(Slot.BELT, 128);
            weaponsmap.Add(Slot.LeftHand, 256);
            weaponsmap.Add(Slot.NCU1, 512);
            weaponsmap.Add(Slot.NCU2, 1024);
            weaponsmap.Add(Slot.NCU3, 2048);
            weaponsmap.Add(Slot.NCU4, 4096);
            weaponsmap.Add(Slot.NCU5, 8192);
            weaponsmap.Add(Slot.NCU6, 16384);

            Dictionary<Slot, int> clothingmap = new Dictionary<Slot, int>();
            clothingmap.Add(Slot.Neck, 2);
            clothingmap.Add(Slot.Head, 4);
            clothingmap.Add(Slot.Back, 8);
            clothingmap.Add(Slot.RightShoulder, 16);
            clothingmap.Add(Slot.Chest, 32);
            clothingmap.Add(Slot.LeftShoulder, 64);
            clothingmap.Add(Slot.RightArm, 128);
            clothingmap.Add(Slot.Hands, 256);
            clothingmap.Add(Slot.LeftArm, 512);
            clothingmap.Add(Slot.RightWrist, 1024);
            clothingmap.Add(Slot.Legs, 2048);
            clothingmap.Add(Slot.LeftWrist, 4096);
            clothingmap.Add(Slot.RightFinger, 8192);
            clothingmap.Add(Slot.Feet, 16384);
            clothingmap.Add(Slot.LeftFinger, 32768);

            Dictionary<Slot, int> implantmap = new Dictionary<Slot, int>();
            implantmap.Add(Slot.Eye, 2);
            implantmap.Add(Slot.Head, 4);
            implantmap.Add(Slot.Ear, 8);
            implantmap.Add(Slot.RightArm, 16);
            implantmap.Add(Slot.Chest, 32);
            implantmap.Add(Slot.LeftArm, 64);
            implantmap.Add(Slot.RightWrist, 128);
            implantmap.Add(Slot.Waist, 256);
            implantmap.Add(Slot.LeftWrist, 512);
            implantmap.Add(Slot.RightHand, 1024);
            implantmap.Add(Slot.Legs, 2048);
            implantmap.Add(Slot.LeftHand, 4096);
            implantmap.Add(Slot.Feet, 8192);

            StringBuilder builder = new StringBuilder("http://auno.org/ao/equip.php?noedit=1");
            
            builder.Append(BuildAunoUrlPart(weaponsmap, weaponGrid, 1));
            builder.Append(BuildAunoUrlPart(clothingmap, clothingGrid, 2));
            builder.Append(BuildAunoUrlPart(implantmap, implantGrid, 3));
            return builder.ToString();
        }

        private string BuildAunoUrlPart(Dictionary<Slot, int> map, EquipmentGrid grid, int index)
        {
            StringBuilder builder = new StringBuilder();
            foreach (IconDockPanel panel in grid.Children)
            {
                if (panel.SelectedItem != null)
                {
                    builder.AppendFormat("&id{3}-{0}={1}&ql2-{0}={2}", map[panel.Slot], panel.SelectedItem.Id, panel.SelectedItem.Ql, index);
                }
            }
            return builder.ToString();
        }
    }
}
